package anatex.kea.stemmers;

import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;

import org.apache.log4j.Logger;

import anatex.domain.CustomLocale;
import anatex.domain.Stopword;
import anatex.kea.genex.GenEx;
import anatex.kea.genex.extractor.Parameters;

public class PhraseStemmer {
	
	CustomLocale loc = null;
	Locale locale = null;
	ArrayList<String> words = null;
	ArrayList<ArrayList<String>> stemPhrases = null;
	ArrayList<String> stopWords = null;
	Stemmer stemmer = null;
	int[] phraseCounts = {0, 0, 0};
	
	public static Logger logger = Logger.getLogger("kea");
	
	public PhraseStemmer() {
		
	}
	
	public PhraseStemmer(ArrayList<String> w, CustomLocale l) {
		words = w;
		
		setCustomLocale(l);
	}
	
	public void setCustomLocale(CustomLocale loc) {
		this.loc = loc;
		
		locale = new Locale(loc.getShort_language(), loc.getShort_language());
		
		stemmer = StemmerFactory.getStemmer(loc);
	}
	
	protected ArrayList<String> getStopWords() {
		if (null == stopWords) {
			stopWords = new ArrayList<String>();
			
			//TODO must get locale from doc
			List<Stopword> s = Stopword.findStopwordsByCustomLocale(loc).getResultList();
			Iterator<Stopword> sit = s.iterator();
			
			while (sit.hasNext()) {
				stopWords.add(sit.next().getWord());
			}
		}
		
		return stopWords;
	}
	
	protected void removeStopwords() {
		stemPhrases.set(1, (ArrayList<String>)words.clone());
		String word;

		//lowecase stems
		ListIterator<String> it = (ListIterator<String>)stemPhrases.get(1).listIterator();
		while (it.hasNext()) {
			word = it.next().toLowerCase();
			it.set(word);
		}
		
		//remove stopwords
		ArrayList<String> sw = getStopWords();
		stemPhrases.get(1).removeAll(sw);
		
		it = (ListIterator<String>)stemPhrases.get(0).listIterator();
		
		int length = 0;
		while (it.hasNext()) {
			word = (String)it.next();
			
			if (word.length() < 3) {
				it.remove();
			} else {
				it.set(stemmer.stem(word));
			}
		}
	}
	
	protected void stem() {
		//1. Find Single Stems
		removeStopwords();
		removeSingleStems(stemPhrases.get(0));
	}
	
	protected void removeSingleStems(ArrayList<String> stemPhrases) {
		Iterator<String> it = stemPhrases.iterator();
		String element = "";
		int timesFound = 0;
		
		while (it.hasNext()) {
			element = it.next();
			
			if (stemPhrases.indexOf(element) == stemPhrases.lastIndexOf(element)) {
				it.remove();
			}
		}
	}
	
	protected void stemPhrases(String text) {
		stemPhrases = new ArrayList<ArrayList<String>>();
		
		//4. Find Stem Phrases
		stemPhrases = new ArrayList<ArrayList<String>>();
		
		stemPhrases.add(new ArrayList<String>());
		stemPhrases.add(new ArrayList<String>());
		stemPhrases.add(new ArrayList<String>());
		stemPhrases.add(new ArrayList<String>());
		getStopWords();
		
		logger.info(text);
		
		for (int i = 1; i <= 3; i ++) {
			BreakIterator it = BreakIterator.getWordInstance(locale);
			
			it.setText(text);
			int start = it.first();
			int end = it.next();
			int skipped = 0;
			Boolean breakPhrase = false;
			
			while (BreakIterator.DONE != end) {
				ArrayList<String> words = new ArrayList<String>();
				breakPhrase = false;
				skipped = 0;
				
				int j = i;
				for (; j >= 1; j --) {
					words.add(text.substring(start, end));
					
					logger.info("added " + text.substring(start, end) + " with boundries " + start + "-" + end);
					
					start = end;
					end = it.next();
					
					logger.info("words is now: " + words.toString());
					
					if (Character.isSpaceChar(words.get(i - j).charAt(0))) {
						words.remove(i - j);
						
						logger.info("Last word removed due to first char being a space - will perform a skip");
						
						skipped ++;
						j ++;
					} else if (! Character.isLetterOrDigit(words.get(i - j).charAt(0))) {
						words.remove(i - j);
						
						logger.info("Last word removed due to first char being non letter or digit - will perform skip.");
						
						breakPhrase = true;
						break;
					} else if (words.get(i - j).length() < 3) {
						words.remove(i - j);
						
						logger.info("Last word removed due to length less than 3 chars - will break phrase.");
						
						breakPhrase = true;
						break;
					} else if (stopWords.contains(words.get(i - j))) {
						words.remove(i - j);
						
						logger.info("Last word removed due to being a stopword - will break phrase.");
						
						breakPhrase = true;
						break;
					}
				}
				
				for (; j < i; j ++) {
					start = it.previous();
				}
				
				while (skipped > 0) {
					start = it.previous();
					skipped --;
				}
				end = it.next();
				
				if (! breakPhrase) {
					StringBuffer sb = new StringBuffer();
					Iterator<String> si = words.iterator();
					
					//TODO must check if word is a proper noun - if so - skip it
					
					while (si.hasNext()) {
						String w = si.next();
						
						sb.append(stemmer.stem(w.toLowerCase()));
						sb.append(" ");
					}
					
					stemPhrases.get(i).add(sb.toString().trim());
				}
				
				start = end;
				end = it.next();
				
				logger.info("End of iteration: " + start + " + " + end);
			}
		}
		
		removeSingleStems(stemPhrases.get(1));
		removeSingleStems(stemPhrases.get(2));
		removeSingleStems(stemPhrases.get(3));
	}
	
	public ArrayList<String> getStems() {
		
		if (null == stemPhrases.get(0)) {
			stem();
		}
		
		return stemPhrases.get(0);
	}
	
	public ArrayList<ArrayList<String>> getStemPhrases(String text) {
		
		if (null == stemPhrases) {
			stemPhrases(text);
		}
		
		return stemPhrases;
	}
	
}
